package com.octopus.optiworks.controller;

import javax.servlet.http.HttpServletRequest;

import com.octopus.optiworks.action.StepActionUtil;
import com.octopus.optiworks.model.Employee;
import com.octopus.optiworks.service.StepService;
import com.octopus.optiworks.service.UserService;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Sha256Hash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Web controller used when loading the home page.
 */
@Controller
@RequestMapping("/common")
public class CommonController {
	
    private LoginValidator loginValidator = new LoginValidator();
    
    private UserValidator userValidator = new UserValidator();
    
	@Autowired
	private StepService stepService;

    @Autowired
    private UserService userService;

    @RequestMapping("/home.o")
    public void viewHome(Model model) {
    	Employee user =  this.userService.getCurrentUser();
    	model.addAttribute("currentUser", user);
    	model.addAttribute("myCurTasks", this.stepService.countProductsByPermissions(null));
    	SearchCommand command = new SearchCommand();
    	command.setStep(StepActionUtil.TESTRESULT_FAILURE);
    	model.addAttribute("myFailTasks", this.stepService.countProductsByPermissions(command));
    	command.setStep(StepActionUtil.TESTRESULT_WAIVE);
    	model.addAttribute("myWaiveTasks", this.stepService.countProductsByPermissions(command));
    }

    @RequestMapping(value="/login.o",method= RequestMethod.GET)
    public String showLoginForm(Model model, @ModelAttribute LoginCommand command ) {
        return "common/login";
    }

    @RequestMapping(value="/login.o",method= RequestMethod.POST)
    public String login(Model model, HttpServletRequest request, @ModelAttribute LoginCommand command, BindingResult errors) {
    	loginValidator.validate(command, errors);
        if( errors.hasErrors() ) {
            return showLoginForm(model, command);
        }
        UsernamePasswordToken token = new UsernamePasswordToken(command.getUsername(), command.getPassword(), command.isRememberMe());
        try {
            SecurityUtils.getSubject().login(token);
        } catch (AuthenticationException e) {
            errors.reject( "error.login.generic", "Invalid username or password.  Please try again." );
        }
        if( errors.hasErrors() ) {
            return showLoginForm(model, command);
        } else {
        	request.getSession().setAttribute("currentUser", this.userService.getCurrentUser());
            return "redirect:/common/home.o";
        }
    }

    @RequestMapping("/logout.o")
    public String logout() {
        SecurityUtils.getSubject().logout();
        return "redirect:/";
    }
    
    @RequestMapping(value="/signup.o",method= RequestMethod.GET)
    public String showSignupForm(Model model, @ModelAttribute Employee user) {
        return "common/signup";
    }

    @RequestMapping(value="/signup.o",method= RequestMethod.POST)
    public String showSignupForm(Model model, @ModelAttribute Employee user, BindingResult errors) {
    	userValidator.validate(user, errors);
        if( errors.hasErrors() ) {
            return showSignupForm(model, user);
        }
        String password = user.getPassword();
        user.setPassword(new Sha256Hash(password).toHex());
        userService.createUser(user, true);
        SecurityUtils.getSubject().login(new UsernamePasswordToken(user.getUsername(), password));
        return "redirect:/common/home.o";
    }
    
    @RequestMapping("/unauthorized.o")
    public void unauthorized(Model model) {
    	Employee user =  this.userService.getCurrentUser();
    	model.addAttribute("currentUser", user);
    }

}
